(function($, undefined) {

var defaults = {
	prefix: 'Template_',
	values: {}
};

var search_var_hide = /{{{([^}]*)}}}/;
var search_var_hide_after = /([a-zA-Z0-9\-_]*)__([^_]*)__/; // replace avar and wrap with underscores
var search_var = /{{([^}]*)}}/; // replace a var and wrap wih span tag
var search = /{([^}]*)}/; // replace a var once
var split_reg = /({=)|({%=)|({%)|(%})|(=})/;

var firstof = function() {
	for ( var i = 0, j = arguments.length; i < j; i++ ) {
		if ( arguments[i] != undefined && arguments[i] !== null ) return arguments[i];
	}
	return '';
};

$.Template = function(args) {
	var opts = $.extend(defaults, args);

	if ( !opts.node ) return;
	var node = ( opts.node && opts.node.jQuery ) ? opts.node : $(opts.node);
	if ( !node[0] ) return;
	var values = args.values || {};

	var html = node.html();
	var parts = html.split(split_reg);
	var code = '';

	for ( var i = 0; i < parts.length; i++ ) {
		if ( typeof parts[i] == 'undefined' ) {         
			parts.splice(i, 1);
			i--;
		}
	}

	for ( var i=0, part; i < parts.length; i++ ) {
		part = parts[i];
		if ( part == '{%' ) {
			i++;
			code += parts[i];
		} else if ( part == '{%=' || part == '{=' ) {
			i++;
			code += '\ntt += ((this.' + parts[i] + ' != undefined)?this.' + parts[i] + ':"");\n';
		} else if ( part == '%}' || part == '=}' ) {
			
		} else {
			code += '\ntt += parts[' + i + '];\n';
		}
	}

	var do_tpl;

	code = 'do_tpl = function() {\nvar tt="";\n' + code + '\nreturn tt;\n};';

	eval(code);

	html = do_tpl.call(values);

	var match;
	var me = this;

	while ( (match = search_var_hide.exec(html)) ) {
		var replace = match[1] + '__';

		if ( typeof values[match[1]] != 'undefined' ) replace += values[match[1]];
		replace += '__';

		html = html.replace(match[0], replace);
	}

	while ( (match = search_var.exec(html)) ) {
		var $node = $('<span/>')
			.addClass('Template_' + match[1]);
		if ( typeof values[match[1]] != 'undefined' ) $node.html(values[match[1]]);

		html = html.replace(match[0], $('<div/>').append($node.eq(0).clone()).html());
	}

	while ( (match = search.exec(html)) ) {
		var value = '';
		var try_val = '';
		
		try {
			eval('value = values.' + match[1]);
		} catch(err) {
			value = '';
		}
		//if ( typeof values[match[1]] != 'undefined' ) value = values[match[1]];
		if ( typeof value == 'undefined' ) value = '';

		html = html.replace(match[0], value);
	}

	this.Node = $(html);

	this.Node.data('Template', this);

	this.Set = function(key, val) {
		if ( val === false ) {
			val = 0;
		} else if ( val === true ) {
			val = 1;
		}
		var cls = '[class*="' + key + '__"]';
		var $node;
		if ( me.Node.is(cls) ) {
			$node = me.Node;
		} else {
			$node = $(cls, me.Node);
		}

		$node.each(function() {
			var search = new RegExp(key + "__([^_]*)__");
			var className = this.className;

			if ( (match = search.exec(className)) ) {
				var replace = key + '__' + val + '__';

				this.className = className.replace(match[0], replace);
			}
		});

		$('.Template_' + key, me.Node).html(val);
	};
};

$.fn.Template = function(args) {
	args = args || {};
	var $node = this.eq(0);
	if ( !$node[0] ) return;
	args.node = $node;
	return new $.Template(args);
};

})(jQuery);